/*
Copyright 2024.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.

// DevcontainerAppSpec defines the desired state of DevcontainerApp
type DevcontainerAppSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	StatefulSet StatefulSetSpec `json:"statefulset"`
	// +optional
	Service ServiceSpec `json:"service"`

	// +kubebuilder:validation:Minimum=0

	// Optional deadline in seconds for starting the job if it misses scheduled
	// time for any reason.  Missed jobs executions will be counted as failed ones.
	// +optional
	StartingDeadlineSeconds *int64 `json:"startingDeadlineSeconds,omitempty"`

	// This flag tells the controller to suspend subsequent executions, it does
	// not apply to already started executions.  Defaults to false.
	// +optional
	Suspend *bool `json:"suspend,omitempty"`

	// +kubebuilder:validation:Minimum=0

	// The number of successful finished jobs to retain.
	// This is a pointer to distinguish between explicit zero and not specified.
	// +optional
	SuccessfulJobsHistoryLimit *int32 `json:"successfulJobsHistoryLimit,omitempty"`

	// +kubebuilder:validation:Minimum=0

	// The number of failed finished jobs to retain.
	// This is a pointer to distinguish between explicit zero and not specified.
	// +optional
	FailedJobsHistoryLimit *int32 `json:"failedJobsHistoryLimit,omitempty"`
}

// StatefulSetSpec specifies StatefulSet for DevContainer
type StatefulSetSpec struct {
	Image   string   `json:"image"`
	Command []string `json:"command"`

	GitRepositoryURL string `json:"gitRepositoryURL"`

	// +kubebuilder:validation:MinItems=1
	// 至少包含一个 SSH Public Key 才能通过校验规则
	SSHPublicKeyList []string `json:"sshPublicKeyList"`

	// +kubebuilder:validation:Minimum=1
	// +optional
	ContainerPort uint16 `json:"containerPort,omitempty"`
}

// ServiceSpec specifies Service for DevContainer
type ServiceSpec struct {
	// +kubebuilder:validation:Minimum=30000
	// +kubebuilder:validation:Maximum=32767
	// +optional
	NodePort uint16 `json:"nodePort,omitempty"`

	// +kubebuilder:validation:Minimum=1
	// +optional
	ServicePort uint16 `json:"servicePort,omitempty"`
}

// DevcontainerAppStatus defines the observed state of DevcontainerApp
type DevcontainerAppStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// A list of pointers to currently running jobs.
	// +optional
	Active []corev1.ObjectReference `json:"active,omitempty"`

	// Information when was the last time the job was successfully scheduled.
	// +optional
	LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"`

	// NodePortAssigned 存储 DevcontainerApp CRD调度后集群分配的 NodePort
	// +optional
	NodePortAssigned uint16 `json:"nodePortAssigned"`

	// Ready 标识 DevcontainerApp 管理的 Pod 的 Readiness Probe 是否达到就绪状态
	// +optional
	Ready bool `json:"ready"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// DevcontainerApp is the Schema for the devcontainerapps API
type DevcontainerApp struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   DevcontainerAppSpec   `json:"spec,omitempty"`
	Status DevcontainerAppStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// DevcontainerAppList contains a list of DevcontainerApp
type DevcontainerAppList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []DevcontainerApp `json:"items"`
}
